﻿#Region "   Imports"

Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Drawing
Imports System.Data
Imports System.Text
Imports System.Drawing.Imaging
Imports System.Windows.Forms
Imports System.Drawing.Drawing2D

#End Region

#Region "   Color Picker Button User Control    "

''' <summary>
''' Color Picker Button Class
''' </summary>
''' <remarks>Version 1.0.0</remarks>
<ToolboxItem(True), ToolboxBitmap(GetType(ColorPickerButton), "ColorPicker.ColorPickerButton.bmp"), ToolboxItemFilter("System.Windows.Forms"), Description("Display the DropDown Color Box.")> _
<DefaultEvent("PickedColorChange"), DefaultProperty("Text")> _
Public Class ColorPickerButton
    Inherits System.Windows.Forms.Button
    Public Event PickedColorChange(ByVal PickedColor As Color)

#Region "   Constructor"
    ''' <summary>
    ''' Required by the Form Designer Variable
    ''' </summary>
    Private Components As System.ComponentModel.IContainer

    ''' <summary>
    ''' Create New Object of ColorPickerButton and Initialize it.
    ''' </summary>
    Public Sub New()
        InitializeComponent()
        Me.SetStyle(ControlStyles.SupportsTransparentBackColor Or ControlStyles.UserPaint Or ControlStyles.ResizeRedraw, True)
        Me.SetStyle(ControlStyles.Opaque, False)
        Me.FlatAppearance.BorderSize = 0
        Me.FlatStyle = Windows.Forms.FlatStyle.Flat
        Me.BackColor = Color.Transparent
        Timer1.Interval = 5
        AddHandler Timer1.Tick, AddressOf Timer1_Tick
    End Sub

#Region "   Component Designer"
    ''' <summary>
    ''' Initialize the Color Picker Button Components
    ''' </summary>
    Public Sub InitializeComponent()
        Me.SuspendLayout()
        Me.Name = "ColorPickerButton"
        Me.Size = New System.Drawing.Size(40, 25)
        Me.Image = My.Resources.PickColor
        Me.ImageSize = New Size(13, 12)
        Me.SplitButton = iSplitButton.Yes
        Me.SplitDistance = 16
        Me.Arrow = iArrow.ToDown
        Me.SplitLocation = iSplitLocation.Right
        Me.ImageAlign = ContentAlignment.TopCenter
        Me.Text = String.Empty
        Me.ResumeLayout(False)
    End Sub

#End Region
    ''' <summary>
    ''' Color Picker Button Overrides Dispose to CleanUp component list
    ''' </summary>
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (Components Is Nothing) Then
                Components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    ''' <summary>
    ''' Create Base for ColorPickerButton
    ''' </summary>
    Protected Overrides Sub OnCreateControl()
        MyBase.OnCreateControl()
        A0 = BaseColor.A
        R0 = BaseColor.R
        G0 = BaseColor.G
        B0 = BaseColor.B
        _ColorStroke = _BaseStroke
        Dim r As Rectangle = New Rectangle(New Point(-1, -1), New Size(Me.Width + _Radius, Me.Height + _Radius))
        If Me.Size <> Nothing Then
            Dim pathregion As GraphicsPath = New GraphicsPath
            DrawArc(r, pathregion)
            Me.Region = New Region(pathregion)
        End If
    End Sub

#End Region

#Region "   Image Settings Properties"

    Private _splitlocation As iSplitLocation
    ''' <summary>
    ''' Enum to Set Split Location for GlasButton
    ''' </summary>
    Public Enum iSplitLocation
        Right
        None
    End Enum
    ''' <summary>
    ''' Get or Set the Location to Split Button into Two Parts
    ''' </summary>
    <Category("ColorPickerButton Appearance"), _
    Description("Split location for ColorPickerButton"), _
    DefaultValue(iSplitLocation.Right), Browsable(True)> _
    Public Property SplitLocation() As iSplitLocation
        Get
            Return _splitlocation
        End Get
        Set(ByVal value As iSplitLocation)
            _splitlocation = value
            Me.Refresh()
        End Set
    End Property

    Private _ImageSize As Size = New Size(24, 24)
    ''' <summary>
    ''' Get or Set the Image Size for ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Image Settings"), _
    Description("Set Image Size of ColorPickerButton"), _
    DefaultValue("24,24"), Browsable(True)> _
    Public Property ImageSize() As Size
        Get
            Return _ImageSize
        End Get
        Set(ByVal value As Size)
            _ImageSize = value
        End Set
    End Property

#End Region

#Region "   Button Settings Properties"

    Private _Imageoffset As Integer = 0
    Private _Radius As Integer = 6
    Private _Showbase As iShowBase
    Private _TempShowBase As iShowBase
    ''' <summary>
    ''' Enum for Base Visibility
    ''' </summary>
    Public Enum iShowBase
        Yes
        No
    End Enum

    ''' <summary>
    ''' Get or Set Base Visibility for ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Settings"), _
    Description("Display Glass Style Base for ColorPickerButton"), _
    DefaultValue(iShowBase.Yes), Browsable(True)> _
    Public Property ShowBase() As iShowBase
        Get
            Return _Showbase
        End Get
        Set(ByVal value As iShowBase)
            _Showbase = value
            Me.Refresh()
        End Set
    End Property

    ''' <summary>
    ''' Get or Set Corner Radius for ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Settings"), _
    Description("Radius of ColorPickerButton Corners"), _
    DefaultValue(6), Browsable(True)> _
    Public Property Radius() As Integer
        Get
            Return _Radius
        End Get
        Set(ByVal value As Integer)
            If _Radius > 2 Then
                _Radius = value
            End If
            Me.Refresh()
        End Set
    End Property

    ''' <summary>
    ''' Enum for Group Position of ColorPickerButton
    ''' </summary>
    Public Enum iGroupPos
        None
        Left
        Center
        Right
        Top
        Bottom
    End Enum

    ''' <summary>
    ''' Get or Set Group Position for ColorPickerButton
    ''' </summary>
    Private _grouppos As iGroupPos
    <Category("ColorPickerButton Position"), _
    Description("Set the Group Position for ColorPickerButton"), _
    DefaultValue(iGroupPos.None), Browsable(True)> _
    Public Property GroupPosition() As iGroupPos
        Get
            Return _grouppos
        End Get
        Set(ByVal value As iGroupPos)
            _grouppos = value
            Me.Refresh()
        End Set
    End Property

    Public Enum iArrow
        None
        ToRight
        ToDown
    End Enum
    Private _Arrow As iArrow
    ''' <summary>
    ''' Get or Set Arrow visibility of ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Arrow"), _
    Description("Display Arrow on ColorPickerButton"), _
    DefaultValue(iArrow.None), Browsable(True)> _
    Public Property Arrow() As iArrow
        Get
            Return _Arrow
        End Get
        Set(ByVal value As iArrow)
            _Arrow = value
            Me.Refresh()
        End Set
    End Property

    Private _Splitbutton As iSplitButton = iSplitButton.No
    Public Enum iSplitButton
        Yes
        No
    End Enum
    ''' <summary>
    ''' Get or Set Split Option for ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Split Settings"), _
    Description("Split ColorPickerButton into Two Parts"), _
    DefaultValue(iSplitButton.No), Browsable(False)> _
    Public Property SplitButton() As iSplitButton
        Get
            Return _Splitbutton
        End Get
        Set(ByVal value As iSplitButton)
            _Splitbutton = value
            Me.Refresh()
        End Set
    End Property

    Private _Splitdistance As Integer = 0
    ''' <summary>
    ''' Get or Set Split Distance for ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Split Settings"), _
    Description("Set Split Distance for ColorPickerButton"), _
    DefaultValue(0), Browsable(True)> _
    Public Property SplitDistance() As Integer
        Get
            Return _Splitdistance
        End Get
        Set(ByVal value As Integer)
            _Splitdistance = value
            Me.Refresh()
        End Set
    End Property

    Private _Keeppressed As Boolean = False
    ''' <summary>
    ''' Get or Set Button State of ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Appearance"), _
    Description("Keep ColorPickerButton Pressed if Clicked"), _
    DefaultValue(False), Browsable(True)> _
    Public Property KeepPressed() As Boolean
        Get
            Return _Keeppressed
        End Get
        Set(ByVal value As Boolean)
            _Keeppressed = value
        End Set
    End Property

    Private _Ispressed As Boolean = False
    ''' <summary>
    ''' Get or Set State of ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Appearance"), _
    Description("Keep ColorPickerButton Selected if Focused"), _
    DefaultValue(False), Browsable(True)> _
    Public Property IsPressed() As Boolean
        Get
            Return _Ispressed
        End Get
        Set(ByVal value As Boolean)
            _Ispressed = value
        End Set
    End Property

#End Region

#Region "   Menu Position"
    Private _menupos As Point = New Point(0, 0)
    ''' <summary>
    ''' Get ot Set DropDown Menu Position of ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Menu"), _
    Description("Set MenuList Position for ColorPickerButton"), _
    DefaultValue("0, 0"), Browsable(True)> _
    Public Property MenuListPosition() As Point
        Get
            Return _menupos
        End Get
        Set(ByVal value As Point)
            _menupos = value
        End Set
    End Property
#End Region

#Region "   Colors"

    Private _BaseColor As Color = Color.FromArgb(211, 211, 211)
    Private _OnColor As Color = Color.FromArgb(255, 214, 78)
    Private _PressColor As Color = Color.FromArgb(255, 128, 0)

    Private _BaseStroke As Color = Color.FromArgb(192, 192, 192)
    Private _OnStroke As Color = Color.FromArgb(196, 177, 118)
    Private _PressStroke As Color = Color.FromArgb(128, 64, 0)
    Private _ColorStroke As Color = Color.FromArgb(255, 255, 255)
    Private A0 As Integer, R0 As Integer, G0 As Integer, B0 As Integer
    ''' <summary>
    ''' Get or Set Base Color for ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Color"), _
    Description("Set Base Color of ColorPickerButton"), _
    DefaultValue("186, 209, 240"), Browsable(True)> _
    Public Property BaseColor() As Color
        Get
            Return _BaseColor
        End Get
        Set(ByVal value As Color)
            _BaseColor = value
            R0 = _BaseColor.R
            B0 = _BaseColor.B
            G0 = _BaseColor.G
            A0 = _BaseColor.A
            Dim hsb As QColor = New QColor(_BaseColor)
            If hsb.BC < 50 Then
                hsb.SetBrightness(60)
            Else
                hsb.SetBrightness(30)
            End If
            If _BaseColor.A > 0 Then
                _BaseStroke = Color.FromArgb(100, hsb.GetColor())
            Else
                _BaseStroke = Color.FromArgb(0, hsb.GetColor())
            End If
            Me.Refresh()
        End Set
    End Property
    ''' <summary>
    ''' Get ot Set OnColor of ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Color"), _
    Description("Set Mouse On Color of ColorPickerButton"), _
    DefaultValue("255, 214, 78"), Browsable(True)> _
    Public Property OnColor() As Color
        Get
            Return _OnColor
        End Get
        Set(ByVal value As Color)
            _OnColor = value

            Dim hsb As QColor = New QColor(_OnColor)
            If (hsb.BC < 50) Then
                hsb.SetBrightness(60)
            Else
                hsb.SetBrightness(30)
            End If
            If (_BaseStroke.A > 0) Then
                _OnStroke = Color.FromArgb(100, hsb.GetColor())
            Else
                _OnStroke = Color.FromArgb(0, hsb.GetColor())
            End If
            Me.Refresh()
        End Set
    End Property
    ''' <summary>
    ''' Get or Set Color when ColorPickerButton is Pressed.
    ''' </summary>
    <Category("ColorPickerButton Color"), _
    Description("Set Mouse Press Color of ColorPickerButton"), _
    DefaultValue("255, 128, 0"), Browsable(True)> _
    Public Property PressColor() As Color
        Get
            Return _PressColor
        End Get
        Set(ByVal value As Color)
            _PressColor = value

            Dim hsb As QColor = New QColor(_PressColor)
            If (hsb.BC < 50) Then
                hsb.SetBrightness(60)
            Else

                hsb.SetBrightness(30)
            End If
            If _BaseStroke.A > 0 Then
                _PressStroke = Color.FromArgb(100, hsb.GetColor())
            Else
                _PressStroke = Color.FromArgb(0, hsb.GetColor())
            End If
            Me.Refresh()
        End Set
    End Property
    ''' <summary>
    ''' Get or Set Base Stroke for ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Color"), _
    Description("Set Base Stroke Color of ColorPickerButton"), _
    DefaultValue("152, 187, 213"), Browsable(True)> _
    Public Property BaseStrokeColor() As Color
        Get
            Return _BaseStroke
        End Get
        Set(ByVal value As Color)
            _BaseStroke = value
        End Set
    End Property
    ''' <summary>
    ''' Get or Set OnStroke Color for ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Color"), _
    Description("Set On Stroke Color of ColorPickerButton"), _
    DefaultValue("196, 177, 118"), Browsable(True)> _
    Public Property OnStrokeColor() As Color
        Get
            Return _OnStroke
        End Get
        Set(ByVal value As Color)
            _OnStroke = value
        End Set
    End Property
    ''' <summary>
    ''' Get or Set PressStroke Color of ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Color"), _
    Description("Set Press Stroke Color of ColorPickerButton"), _
    DefaultValue("128, 64, 0"), Browsable(True)> _
    Public Property PressStrokeColor() As Color
        Get
            Return _PressStroke
        End Get
        Set(ByVal value As Color)
            _PressStroke = value
        End Set
    End Property
    ''' <summary>
    ''' Get or Set Picked Color of ColorPickerButton
    ''' </summary>
    Public Property PickedColor() As Color
        Get
            Return _SelectedColor
        End Get
        Set(ByVal value As Color)
            _SelectedColor = value
            RaiseEvent PickedColorChange(_SelectedColor)
        End Set
    End Property
    ''' <summary>
    ''' Return Color with Increase Value
    ''' </summary>
    ''' <param name="color">The Value As System.Drawing.Color</param>
    ''' <param name="h">Hue Value As Integer</param>
    ''' <param name="s">Saturation Value As Integer</param>
    ''' <param name="b">Brightness Value As Integer</param>
    ''' <returns>Returns New Color</returns>
    Public Function GetColorIncreased(ByVal color As Color, ByVal h As Integer, ByVal s As Integer, ByVal b As Integer) As Color
        Dim _color As QColor = New QColor(color)
        Dim ss As Integer = _color.GetSaturation()
        Dim vc As Single = b + _color.GetBrightness()
        Dim hc As Single = h + _color.GetHue()
        Dim sc As Single = s + ss
        _color.VC = vc
        _color.HC = hc
        _color.SC = sc
        Return _color.GetColor()
    End Function
    ''' <summary>
    ''' Returns New Color From ARGB Values
    ''' </summary>
    ''' <param name="A">Alpha value as Integer</param>
    ''' <param name="R">Red value as integer</param>
    ''' <param name="G">Green value as Integer</param>
    ''' <param name="B">Blue value as Integer</param>
    ''' <returns>New Color</returns>
    Public Function GetColor(ByVal A As Integer, ByVal R As Integer, ByVal G As Integer, ByVal B As Integer)
        If (A + A0 > 255) Then
            A = 255
        Else
            A = A + A0
        End If
        If (R + R0 > 255) Then
            R = 255
        Else
            R = R + R0
        End If
        If (G + G0 > 255) Then
            G = 255
        Else
            G = G + G0
        End If
        If B + B0 > 255 Then
            B = 255
        Else
            B = B + B0
        End If
        Return Color.FromArgb(A, R, G, B)
    End Function

#End Region

#Region "   ColorPickerButton Methods"
    ''' <summary>
    ''' Handles ColorPickerButton Paint
    ''' </summary>
    Protected Overrides Sub OnPaint(ByVal pevent As System.Windows.Forms.PaintEventArgs)
        Dim g As Graphics = pevent.Graphics
        g.SmoothingMode = SmoothingMode.HighQuality
        g.InterpolationMode = InterpolationMode.High
        Dim r As Rectangle = New Rectangle(New Point(-1, -1), New Size(Me.Width + _Radius, Me.Height + _Radius))
        Dim path As GraphicsPath = New GraphicsPath
        Dim rp As Rectangle = New Rectangle(New Point(0, 0), New Size(Me.Width - 1, Me.Height - 1))
        DrawArc(rp, path)
        FillGradients(g, path)
        DrawImage(g)
        DrawArrow(g)
        DrawColorBar(g)
    End Sub
    ''' <summary>
    ''' Handles ColorPickerButton Resize
    ''' </summary>
    Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
        Dim r As Rectangle = New Rectangle(New Point(-1, -1), New Size(Me.Width + _Radius, Me.Height + _Radius))
        If (Me.Size <> Nothing) Then
            Dim pathregion As GraphicsPath = New GraphicsPath()
            DrawArc(r, pathregion)
            Me.Region = New Region(pathregion)
        End If
        MyBase.OnResize(e)
    End Sub

#End Region

#Region "   Paint Methods"

    ''' <summary>
    ''' Handles Glowing of ColorPickerButton
    ''' </summary>
    Public Sub FillGradients(ByVal gr As Graphics, ByVal pa As GraphicsPath)
        Dim _origin As Integer = Me.Height / 3
        Dim _end As Integer = Me.Height
        Dim _oe As Integer = (_end - _origin) / 2
        Dim lgbrush As LinearGradientBrush
        Dim rect As Rectangle
        If _Showbase = iShowBase.Yes Then
            rect = New Rectangle(New Point(0, 0), New Size(Me.Width - 1, Me.Height - 1))
            pa = New GraphicsPath()
            DrawArc(rect, pa)
            lgbrush = New LinearGradientBrush(rect, Color.Transparent, Color.Transparent, LinearGradientMode.Vertical)
            Dim pos As Single() = New Single(3) {0.0F, 0.3F, 0.35F, 1.0F}
            Dim colors As Color()
            If I_Mode = 0 Then
                colors = New Color(3) {GetColor(0, 35, 24, 9), GetColor(0, 13, 8, 3), Color.FromArgb(A0, R0, G0, B0), GetColor(0, 28, 29, 14)}
            Else
                colors = New Color(3) {GetColor(0, 0, 50, 100), GetColor(0, 0, 0, 30), Color.FromArgb(A0, R0, G0, B0), GetColor(0, 0, 50, 100)}
            End If
            Dim mix As ColorBlend = New ColorBlend()
            mix.Colors = colors
            mix.Positions = pos
            lgbrush.InterpolationColors = mix
            gr.FillPath(lgbrush, pa)
            rect = New Rectangle(New Point(0, 0), New Size(Me.Width, Me.Height / 3))
            pa = New GraphicsPath()
            Dim _rtemp As Integer = _Radius
            _Radius = _rtemp - 1
            DrawArc(rect, pa)
            If (A0 > 80) Then
                gr.FillPath(New SolidBrush(Color.FromArgb(60, 255, 255, 255)), pa)
            End If
            _Radius = _rtemp
            If (_Splitbutton = iSplitButton.Yes And Mouse) Then
                FillSplitPart(gr)
            End If
            If (I_Mode = 2) Then
                rect = New Rectangle(1, 1, Me.Width - 2, Me.Height)
                pa = New GraphicsPath()
                DrawShadow(rect, pa)
                gr.DrawPath(New Pen(Color.FromArgb(50, 20, 20, 20), 2.0F), pa)
            Else
                rect = New Rectangle(1, 1, Me.Width - 2, Me.Height - 1)
                pa = New GraphicsPath()
                DrawShadow(rect, pa)
                If (A0 > 80) Then
                    gr.DrawPath(New Pen(Color.FromArgb(100, 250, 250, 250), 3.0F), pa)
                End If
            End If
            If (_Splitbutton = iSplitButton.Yes) Then
                If (_splitlocation = iSplitLocation.Right) Then
                    Select Case I_Mode
                        Case 1
                            gr.DrawLine(New Pen(_OnStroke), New Point(Me.Width - _Splitdistance, 0), New Point(Me.Width - _Splitdistance, Me.Height))
                        Case 2
                            gr.DrawLine(New Pen(_PressStroke), New Point(Me.Width - _Splitdistance, 0), New Point(Me.Width - _Splitdistance, Me.Height))
                    End Select
                End If
            End If
            rect = New Rectangle(New Point(0, 0), New Size(Me.Width - 1, Me.Height - 1))
            pa = New GraphicsPath()
            DrawArc(rect, pa)
            gr.DrawPath(New Pen(_ColorStroke, 0.9F), pa)
            pa.Dispose()
            lgbrush.Dispose()
        End If
    End Sub
    Dim offsetx As Integer = 0, offsety As Integer = 0, imageheight As Integer = 0, imagewidth As Integer = 0
    ''' <summary>
    ''' Draw Image On ColorPickerButton
    ''' </summary>
    ''' <param name="gr"></param>
    ''' <remarks></remarks>
    Public Sub DrawImage(ByVal gr As Graphics)
        If Me.Image Is Nothing Then Return
        Dim r As Rectangle = New Rectangle(8, 8, Me.ImageSize.Width, Me.ImageSize.Height)
        Select Case Me.ImageAlign
            Case ContentAlignment.TopLeft
                r = New Rectangle(4, 4, Me.ImageSize.Width, Me.ImageSize.Height)
            Case ContentAlignment.TopCenter
                r = New Rectangle((Me.Width / 2 - Me.ImageSize.Width / 2) / 2, 4, Me.ImageSize.Width, Me.ImageSize.Height)
            Case ContentAlignment.TopRight
                r = New Rectangle(Me.Width - 4 - Me.ImageSize.Width, 4, Me.ImageSize.Width, Me.ImageSize.Height)
            Case ContentAlignment.MiddleLeft
                r = New Rectangle(8, Me.Height / 2 - Me.ImageSize.Height / 2, Me.ImageSize.Width, Me.ImageSize.Height)
            Case ContentAlignment.MiddleCenter
                r = New Rectangle(Me.Width / 2 - Me.ImageSize.Width / 2, Me.Height / 2 - Me.ImageSize.Height / 2, Me.ImageSize.Width, Me.ImageSize.Height)
            Case ContentAlignment.MiddleRight
                r = New Rectangle(Me.Width - 8 - Me.ImageSize.Width, Me.Height / 2 - Me.ImageSize.Height / 2, Me.ImageSize.Width, Me.ImageSize.Height)
            Case ContentAlignment.BottomLeft
                r = New Rectangle(8, Me.Height - 8 - Me.ImageSize.Height, Me.ImageSize.Width, Me.ImageSize.Height)
            Case ContentAlignment.BottomCenter
                r = New Rectangle(Me.Width / 2 - Me.ImageSize.Width / 2, Me.Height - 8 - Me.ImageSize.Height, Me.ImageSize.Width, Me.ImageSize.Height)
            Case ContentAlignment.BottomRight
                r = New Rectangle(Me.Width - 8 - Me.ImageSize.Width, Me.Height - 8 - Me.ImageSize.Height, Me.ImageSize.Width, Me.ImageSize.Height)
        End Select
        gr.DrawImage(Me.Image, r)
    End Sub
    ''' <summary>
    ''' Draw arc for ColorPickerButton
    ''' </summary>
    ''' <param name="re">R As Rectangle</param>
    ''' <param name="pa">Path As Graphics Path</param>
    Public Sub DrawArc(ByVal re As Rectangle, ByVal pa As GraphicsPath)
        If _Radius < 2 Then _Radius = 2
        Dim _radiusX0Y0 As Integer = _Radius, _radiusXFY0 As Integer = _Radius, _radiusX0YF As Integer = _Radius, _radiusXFYF As Integer = _Radius
        Select Case _grouppos
            Case iGroupPos.Left
                _radiusXFY0 = 1
                _radiusXFYF = 1
            Case iGroupPos.Center
                _radiusX0Y0 = 1
                _radiusX0YF = 1
                _radiusXFY0 = 1
                _radiusXFYF = 1
            Case iGroupPos.Right
                _radiusX0Y0 = 1
                _radiusX0YF = 1
            Case iGroupPos.Top
                _radiusX0YF = 1
                _radiusXFYF = 1
            Case iGroupPos.Bottom
                _radiusX0Y0 = 1
                _radiusXFY0 = 1
        End Select
        pa.AddArc(re.X, re.Y, _radiusX0Y0, _radiusX0Y0, 180, 90)
        pa.AddArc(re.Width - _radiusXFY0, re.Y, _radiusXFY0, _radiusXFY0, 270, 90)
        pa.AddArc(re.Width - _radiusXFYF, re.Height - _radiusXFYF, _radiusXFYF, _radiusXFYF, 0, 90)
        pa.AddArc(re.X, re.Height - _radiusX0YF, _radiusX0YF, _radiusX0YF, 90, 90)
        pa.CloseFigure()
    End Sub
    ''' <summary>
    ''' Draw Shadow for ColorPickerButton
    ''' </summary>
    ''' <param name="re">R As Rectangle</param>
    ''' <param name="pa">Path As Graphics Path</param>
    Public Sub DrawShadow(ByVal re As Rectangle, ByVal pa As GraphicsPath)
        Dim _radiusX0Y0 As Integer = _Radius, _radiusXFY0 As Integer = _Radius, _radiusX0YF As Integer = _Radius, _radiusXFYF As Integer = _Radius
        Select Case _grouppos
            Case iGroupPos.Left
                _radiusXFY0 = 1
                _radiusXFYF = 1
            Case iGroupPos.Center
                _radiusX0Y0 = 1
                _radiusX0YF = 1
                _radiusXFY0 = 1
                _radiusXFYF = 1
            Case iGroupPos.Right
                _radiusX0Y0 = 1
                _radiusX0YF = 1
            Case iGroupPos.Top
                _radiusX0YF = 1
                _radiusXFYF = 1
            Case iGroupPos.Bottom
                _radiusX0Y0 = 1
                _radiusXFY0 = 1
        End Select
        pa.AddArc(re.X, re.Y, _radiusX0Y0, _radiusX0Y0, 180, 90)
        pa.AddArc(re.Width - _radiusXFY0, re.Y, _radiusXFY0, _radiusXFY0, 270, 90)
        pa.AddArc(re.Width - _radiusXFYF, re.Height - _radiusXFYF, _radiusXFYF, _radiusXFYF, 0, 90)
        pa.AddArc(re.X, re.Height - _radiusX0YF, _radiusX0YF, _radiusX0YF, 90, 90)
        pa.CloseFigure()

    End Sub
    ''' <summary>
    ''' Draw Arrow on ColorPickerButton
    ''' </summary>
    ''' <param name="gr">graphics As Graphics</param>
    ''' <remarks></remarks>
    Public Sub DrawArrow(ByVal gr As Graphics)
        Dim _size As Integer = 1

        Dim __color As QColor = New QColor(Color.FromArgb(R0, G0, B0))
        Dim forecolor As QColor = New QColor(Me.ForeColor)
        Dim _forecolor As Color
        If (__color.GetBrightness() > 50) Then
            forecolor.BC = 1
            forecolor.SC = 80
        Else
            forecolor.BC = 99
            forecolor.SC = 20
        End If
        _forecolor = forecolor.GetColor()
        Select Case _Arrow
            Case iArrow.ToDown
                If (_splitlocation = iSplitLocation.Right) Then
                    Dim arrowxpos As Integer = Me.Width - _Splitdistance - 4
                    If _Splitdistance = 0 Then arrowxpos = arrowxpos - 10
                    Dim points As Point() = New Point(2) {New Point((_Splitdistance / 2) + arrowxpos + 8 * _size - _Imageoffset, Me.Height / 2 - _size / 2), New Point((_Splitdistance / 2) + arrowxpos + 0.5 * _size - _Imageoffset, Me.Height / 2 - _size / 2), New Point((_Splitdistance / 2) + arrowxpos + 4 * _size - _Imageoffset, Me.Height / 2 + _size * 2)}
                    gr.FillPolygon(New SolidBrush(_forecolor), points)
                End If
            Case iArrow.ToRight
                If (_splitlocation = iSplitLocation.Right) Then
                    Dim arrowxpos As Integer = Me.Width - _Splitdistance + 4 * _Imageoffset
                    If _Splitdistance = 0 Then arrowxpos = arrowxpos - 15
                    Dim points As Point() = New Point(2) {New Point(arrowxpos + 4, Me.Height / 2 - 4 * _size), New Point(arrowxpos + 8, Me.Height / 2), New Point(arrowxpos + 4, Me.Height / 2 + 4 * _size)}
                    gr.FillPolygon(New SolidBrush(_forecolor), points)
                End If
        End Select
    End Sub
    ''' <summary>
    ''' Fill Splitted Part Of ColorPickerButton.
    ''' </summary>
    ''' <param name="g">Graphics As Graphics Object.</param>
    Public Sub FillSplitPart(ByVal g As Graphics)
        Dim _tranp As Color = Color.FromArgb(200, 255, 255, 255)
        Dim x1 As Int32 = Me.Width - _Splitdistance
        Dim x2 As Int32 = 0
        Dim y1 As Int32 = Me.Height - _Splitdistance, y2 As Int32 = 0
        Dim btransp As SolidBrush = New SolidBrush(_tranp)
        If _splitlocation = iSplitLocation.Right Then
            If XMouse < Me.Width - _Splitdistance And Mouse Then
                Dim _r As Rectangle = New Rectangle(x1 + 1, 1, Me.Width - 2, Me.Height - 1)
                Dim p As GraphicsPath = New GraphicsPath()
                Dim _rtemp As Int32 = _Radius
                _Radius = 4
                DrawArc(_r, p)
                _Radius = _rtemp
                g.FillPath(btransp, p)
            ElseIf Mouse Then
                Dim _r As Rectangle = New Rectangle(x2 + 1, 1, Me.Width - _Splitdistance - 1, Me.Height - 1)
                Dim p As GraphicsPath = New GraphicsPath()
                Dim _rtemp As Int32 = _Radius
                _Radius = 4
                DrawArc(_r, p)
                _Radius = _rtemp
                g.FillPath(btransp, p)
            End If
        End If
        btransp.Dispose()
    End Sub

    Private _SelectedColor As Color = Color.Black
    ''' <summary>
    ''' Draw Color Bar at Bottom Of ColorPickerButton and Fill it With Selected Color
    ''' </summary>
    ''' <param name="g">Graphics As Graphics Object.</param>
    ''' <remarks></remarks>
    Public Sub DrawColorBar(ByVal g As Graphics)
        Dim _ColorRect As Rectangle = New Rectangle()
        If SplitButton = iSplitButton.Yes Then
            _ColorRect = New Rectangle(5, Me.Height - 8, (Me.Width - 10) - Me._Splitdistance, 3)
        Else
            _ColorRect = New Rectangle(5, Me.Height - 8, Me.Width - 10, 3)
        End If
        g.FillRectangle(New SolidBrush(PickedColor), _ColorRect)
    End Sub

#End Region

#Region "   Fading Properties"
    Private Timer1 As Timer = New Timer
    Dim i_factor As Int32 = 35
    ''' <summary>
    ''' Get or Set Fading Speeed of ColorPickerButton
    ''' </summary>
    <Category("ColorPickerButton Appearance"), _
    Description("Set Fading Speed of ColorPickerButton"), _
    DefaultValue(35), Browsable(True)> _
    Public Property GlowingingSpeed() As Int32
        Get
            Return i_factor
        End Get
        Set(ByVal value As Int32)
            If value > -1 Then i_factor = value
        End Set
    End Property

    Dim i_fR As Int32 = 1, i_fG As Int32 = 1, i_fB As Int32 = 1, i_fA As Int32 = 1
    ''' <summary>
    ''' Handles Timer Tick for ColorPickerButton
    ''' </summary>
    ''' <param name="sender">sender As Object</param>
    ''' <param name="e">e As EventArgs</param>
    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As EventArgs)
        If I_Mode = 1 Then
            If (System.Math.Abs(OnColor.R - R0) > i_factor) Then
                i_fR = i_factor
            Else
                i_fR = 1
            End If
            If System.Math.Abs(OnColor.G - G0) > i_factor Then
                i_fG = i_factor
            Else
                i_fG = 1
            End If
            If System.Math.Abs(OnColor.B - B0) > i_factor Then
                i_fB = i_factor
            Else
                i_fB = 1
            End If
            If (OnColor.R < R0) Then
                R0 -= i_fR
            ElseIf (OnColor.R > R0) Then
                R0 += i_fR
            End If
            If (OnColor.G < G0) Then
                G0 -= i_fG
            ElseIf (OnColor.G > G0) Then
                G0 += i_fG
            End If
            If (OnColor.B < B0) Then
                B0 -= i_fB
            ElseIf (OnColor.B > B0) Then
                B0 += i_fB
            End If
            If OnColor = Color.FromArgb(R0, G0, B0) Then
                Timer1.Stop()
            Else
                Me.Refresh()
            End If
        End If
        If I_Mode = 0 Then
            If (System.Math.Abs(BaseColor.R - R0) < i_factor) Then
                i_fR = 1
            Else
                i_fR = i_factor
            End If
            If (System.Math.Abs(BaseColor.G - G0) < i_factor) Then
                i_fG = 1
            Else
                i_fG = i_factor
            End If
            If (System.Math.Abs(BaseColor.B - B0) < i_factor) Then
                i_fB = 1
            Else
                i_fB = i_factor
            End If
            If (System.Math.Abs(BaseColor.A - A0) < i_factor) Then
                i_fA = 1
            Else
                i_fA = i_factor
            End If

            If (BaseColor.R < R0) Then
                R0 -= i_fR
            ElseIf (BaseColor.R > R0) Then
                R0 += i_fR
            End If
            If (BaseColor.G < G0) Then
                G0 -= i_fG
            ElseIf (BaseColor.G > G0) Then
                G0 += i_fG
            End If
            If (BaseColor.B < B0) Then
                B0 -= i_fB
            ElseIf (BaseColor.B > B0) Then
                B0 += i_fB
            End If
            If (BaseColor.A < A0) Then
                A0 -= i_fA
            ElseIf (BaseColor.A > A0) Then
                A0 += i_fA
            End If
            If (BaseColor = Color.FromArgb(A0, R0, G0, B0)) Then
                Timer1.Stop()
            Else
                Me.Refresh()
            End If
        End If
        Me.Refresh()
    End Sub

#End Region

#Region "   Mouse Events"
    Dim I_Mode As Integer = 0
    Dim Mouse As Boolean = False
    Dim XMouse As Int32 = 0, YMouse As Int32 = 0
    ''' <summary>
    ''' Handles Mouse Enter for ColorPickerButton
    ''' </summary>
    Protected Overrides Sub OnMouseEnter(ByVal e As System.EventArgs)
        MyBase.OnMouseEnter(e)
        _ColorStroke = OnStrokeColor
        _TempShowBase = _Showbase
        _Showbase = iShowBase.Yes
        I_Mode = 1
        XMouse = PointToClient(Cursor.Position).X
        Mouse = True
        A0 = 200
        If i_factor = 0 Then
            R0 = _OnColor.R
            G0 = _OnColor.G
            B0 = _OnColor.B
        End If
        Timer1.Start()
    End Sub
    ''' <summary>
    ''' Handles Mouse Leave for ColorPickerButton
    ''' </summary>
    Protected Overrides Sub OnMouseLeave(ByVal e As System.EventArgs)
        MyBase.OnMouseLeave(e)
        UpdateMouseLeave()
    End Sub
    ''' <summary>
    ''' Handles Mouse Leave for ColorPickerButton
    ''' </summary>
    Public Sub UpdateMouseLeave()
        If _Keeppressed = False Or (_Keeppressed = True And _Ispressed = False) Then
            _ColorStroke = BaseStrokeColor
            _Showbase = _TempShowBase
            I_Mode = 0
            Mouse = False
            If i_factor = 0 Then
                R0 = _BaseColor.R
                G0 = _BaseColor.G
                B0 = _BaseColor.B
                Me.Refresh()
            Else
                Timer1.Stop()
                Timer1.Start()
            End If
        End If
    End Sub
    ''' <summary>
    ''' Handles Mouse Down for ColorPickerButton
    ''' </summary>
    Protected Overrides Sub OnMouseDown(ByVal mevent As System.Windows.Forms.MouseEventArgs)
        MyBase.OnMouseDown(mevent)
        R0 = PressColor.R
        G0 = PressColor.G
        B0 = PressColor.B
        _ColorStroke = PressStrokeColor
        _Showbase = iShowBase.Yes
        I_Mode = 2
        XMouse = PointToClient(Cursor.Position).X
        YMouse = PointToClient(Cursor.Position).Y
        Mouse = True
    End Sub
    ''' <summary>
    ''' Handles Mouse Up for ColorPickerButton
    ''' </summary>
    Protected Overrides Sub OnMouseUp(ByVal mevent As System.Windows.Forms.MouseEventArgs)
        R0 = OnColor.R
        G0 = OnColor.G
        B0 = OnColor.B
        _ColorStroke = OnStrokeColor
        _Showbase = iShowBase.Yes
        I_Mode = 1
        Mouse = True
        If _splitlocation = iSplitLocation.Right And XMouse > Me.Width - _Splitdistance And _Splitbutton = iSplitButton.Yes Then
            If (_Arrow = iArrow.ToDown) Then
                Dim _MBColorPicker As ColorPickerHelper = New ColorPickerHelper(Me)
                _MBColorPicker.Show(Me.Parent, New Point(Me.Location.X, Me.Height + Me.Location.Y))
            ElseIf (_Arrow = iArrow.ToRight) Then
                Dim _MBColorPicker As ColorPickerHelper = New ColorPickerHelper(Me)
                _MBColorPicker.Show(Me.Parent, New Point(Me.Location.X + Me.Width, (Me.Location.Y + Me.Height / 2) - _MBColorPicker.Height / 2))
            End If
        Else
            MyBase.OnMouseUp(mevent)
            If (_Keeppressed) Then
                _Ispressed = True
                For Each _control As Control In Me.Parent.Controls
                    If _control.Name <> Me.Name And TypeOf (_control) Is ColorPickerButton = True Then
                        CType(_control, ColorPickerButton)._Ispressed = False
                        CType(_control, ColorPickerButton).UpdateMouseLeave()
                    End If
                Next
            End If
        End If
    End Sub
    ''' <summary>
    ''' Handles Mouse Move for ColorPickerButton
    ''' </summary>
    Protected Overrides Sub OnMouseMove(ByVal mevent As System.Windows.Forms.MouseEventArgs)
        If Mouse And Me.SplitButton = iSplitButton.Yes Then
            XMouse = PointToClient(Cursor.Position).X
            YMouse = PointToClient(Cursor.Position).Y
            Me.Refresh()
        End If
        MyBase.OnMouseMove(mevent)
    End Sub
#End Region

End Class

''' <summary>
''' QColor Class for ColorPickerButton
''' </summary>
Public Class QColor

#Region "   Constructor"
    ''' <summary>
    ''' Constructor for QColor
    ''' </summary>
    ''' <param name="color">Color Value</param>
    Public Sub New(ByVal color As Color)
        _rc = color.R
        _gc = color.G
        _bc = color.B
        _ac = color.A
        HSV()
    End Sub

    ''' <summary>
    ''' Constructor for QColor
    ''' </summary>
    ''' <param name="a">Alpha value</param>
    ''' <param name="r">Red value</param>
    ''' <param name="g">Green value</param>
    ''' <param name="b">Blue value</param>
    Public Sub New(ByVal a As UInteger, ByVal r As Integer, ByVal g As Integer, ByVal b As Integer)
        _hc = r
        _gc = g
        _vc = b
        _ac = a
        GetColor()
    End Sub

#End Region

#Region "   Alpha"
    Private _ac As UInteger = 0
    Public Property AC() As UInteger
        Get
            Return _ac
        End Get
        Set(ByVal value As UInteger)
            System.Math.Min(value, 255)
        End Set
    End Property
#End Region

#Region "   RGB"

    Private _rc As Int32 = 0, _gc As Int32 = 0, _bc As Int32 = 0

    Public Property RC() As Int32
        Get
            Return _rc
        End Get
        Set(ByVal value As Int32)
            _rc = System.Math.Min(value, 255)
        End Set
    End Property

    Public Property GC() As Int32
        Get
            Return _gc
        End Get
        Set(ByVal value As Int32)
            _gc = System.Math.Min(value, 255)
        End Set
    End Property

    Public Property BC() As Int32
        Get
            Return _bc
        End Get
        Set(ByVal value As Int32)
            _bc = System.Math.Min(value, 255)
        End Set
    End Property

    Public Function GetColor() As Color
        Dim conv As Integer
        Dim hue As Double, sat As Double, val As Double
        Dim basis As Integer

        hue = CType(_hc / 100.0F, Single)
        sat = CType(_sc / 100.0F, Single)
        val = CType(_vc / 100.0F, Single)
        If _sc = 0 Then
            conv = (255.0F * val)
            _rc = _gc = _bc = conv
            Return Color.FromArgb(_rc, _gc, _bc)
        End If
        basis = 255.0F * (1.0 - sat) * val
        Select Case _hc / 60.0F
            Case 0
                RC = 255.0F * val
                GC = (255.0F * val - basis) * (HC / 60.0F) + basis
                BC = basis
            Case 1
                RC = ((255.0F * val - basis) * (1.0F - ((HC Mod 60) / 60.0F)) + basis)
                GC = 255.0F * val
                BC = basis
            Case 2
                RC = basis
                GC = (255.0F * val)
                BC = (255.0F * val - basis) * ((HC Mod 60) / 60.0F) + basis
            Case 3
                RC = basis
                GC = (255.0F * val - basis) * (1.0F - ((HC Mod 60) / 60.0F)) + basis
                BC = (255.0F * val)
            Case 4
                RC = ((255.0F * val - basis) * ((HC Mod 60) / 60.0F) + basis)
                GC = basis
                BC = (255.0F * val)
            Case 5
                RC = (255.0F * val)
                GC = basis
                BC = ((255.0F * val - basis) * (1.0F - ((HC Mod 60) / 60.0F)) + basis)
        End Select
        Return Color.FromArgb(_ac, _rc, _gc, _bc)
    End Function

#End Region

#Region "   HSV"
    Private _hc As Int32 = 0, _sc As Int32 = 0, _vc As Int32 = 0

    Public Property HC() As Single
        Get
            Return _hc
        End Get
        Set(ByVal value As Single)
            _hc = System.Math.Min(value, 310)
            _hc = System.Math.Max(HC, 0)
        End Set
    End Property

    Public Property SC() As Single
        Get
            Return _sc
        End Get
        Set(ByVal value As Single)
            _sc = System.Math.Min(value, 100)
            _sc = System.Math.Max(SC, 0)
        End Set
    End Property

    Public Property VC() As Single
        Get
            Return _vc
        End Get
        Set(ByVal value As Single)
            _vc = System.Math.Min(value, 100)
            _vc = System.Math.Max(VC, 0)
        End Set
    End Property

    Public Enum iColor
        RED
        GREEN
        BLUE
        NONE
    End Enum

    Private maxval As Integer = 0, minval As Integer = 0
    Private CompMax As iColor, CompMain As iColor

    Private Sub HSV()
        _hc = Me.GetHue()
        _sc = Me.GetSaturation()
        _vc = Me.GetBrightness()
    End Sub

    Public Sub ColorMax()
        If _rc > _gc Then
            If _rc < _bc Then
                maxval = _bc
                CompMax = iColor.BLUE
            Else
                maxval = _rc
                CompMax = iColor.RED
            End If
        Else
            If _gc < _bc Then
                maxval = _bc
                CompMax = iColor.BLUE
            Else
                maxval = _gc
                CompMax = iColor.GREEN
            End If
        End If
    End Sub

    Public Sub ColorMin()
        If _rc < _gc Then
            If _rc > _bc Then
                maxval = _bc
                CompMax = iColor.BLUE
            Else
                maxval = _rc
                CompMax = iColor.RED
            End If
        Else
            If _gc > _bc Then
                maxval = _bc
                CompMax = iColor.BLUE
            Else
                maxval = _gc
                CompMax = iColor.GREEN
            End If
        End If
    End Sub

    Public Function GetBrightness()
        ColorMax()
        Return 100 * maxval / 255
    End Function

    Public Function GetSaturation()
        ColorMax()
        ColorMin()
        If CompMax = iColor.NONE Then
            Return 0
        ElseIf maxval <> minval Then
            Dim d_sat As Double = Decimal.Divide(minval, maxval)
            d_sat = Decimal.Subtract(1, d_sat)
            d_sat = Decimal.Multiply(d_sat, 100)
            Return Convert.ToUInt16(d_sat)
        Else
            Return 0
        End If
    End Function

    Public Function GetHue() As UInt16
        ColorMax()
        ColorMin()
        If maxval = minval Then
            Return 0
        ElseIf CompMax = iColor.RED Then
            If GC >= BC Then
                Dim d1 As Decimal = Decimal.Divide((GC - BC), (maxval - minval))
                Return Convert.ToUInt16(60 * d1)
            Else
                Dim d1 As Decimal = Decimal.Divide((BC - GC), (maxval - minval))
                d1 = 60 * d1
                Return Convert.ToUInt16(360 - d1)
            End If
        ElseIf CompMax = iColor.GREEN Then
            If (BC >= RC) Then
                Dim d1 As Decimal = Decimal.Divide((BC - RC), (maxval - minval))
                d1 = 60 * d1
                Return Convert.ToUInt16(120 + d1)
            Else
                Dim d1 As Decimal = Decimal.Divide((RC - BC), (maxval - minval))
                d1 = 60 * d1
                Return Convert.ToUInt16(120 - d1)
            End If
        ElseIf CompMax = iColor.BLUE Then
            If (RC >= GC) Then
                Dim d1 As Decimal = Decimal.Divide((RC - GC), (maxval - minval))
                d1 = 60 * d1
                Return Convert.ToUInt16(240 + d1)
            Else
                Dim d1 As Decimal = Decimal.Divide((GC - RC), (maxval - minval))
                d1 = 60 * d1
                Return Convert.ToUInt16(240 - d1)
            End If
        Else
            Return 0
        End If
    End Function

#End Region

#Region "   Methods"

    Public Sub SetBrightness(ByVal val As Integer)
        Me.VC = val
    End Sub

#End Region

End Class

#End Region
